#ifndef PW_PBL_WRAPPINGSEQ_HPP
#define PW_PBL_WRAPPINGSEQ_HPP

#include "pw_pbl/Math.hpp"
#include <concepts>

namespace pw_pbl
{
	template <std::unsigned_integral T>
	class WrappingSeq
	{
		T _v;

	public:
		constexpr WrappingSeq() noexcept : _v(0) {}
		explicit constexpr WrappingSeq(T v) noexcept : _v(v) {}
		constexpr WrappingSeq(const WrappingSeq &) noexcept = default;

		constexpr WrappingSeq next() const
		{
			T v = this->_v;
			auto ov = Math::AddOverflow(1, &v);
			return WrappingSeq(v + ov);
		}
		constexpr bool is_null() const { return this->_v == 0; }
		constexpr T value() const { return this->_v; }
		static WrappingSeq start() { return WrappingSeq(1); }
		constexpr bool operator==(const WrappingSeq &oth) const { return this->_v == oth._v; }
		constexpr WrappingSeq &operator=(const WrappingSeq &oth) = default;

		static inline WrappingSeq &bind(T &v) { return *reinterpret_cast<WrappingSeq *>(&v); }
		static inline const WrappingSeq &bind(const T &v) { return *reinterpret_cast<const WrappingSeq *>(&v); }
	};
} // namespace pw_pbl
#endif // PW_PBL_WRAPPINGSEQ_HPP
